"""
企业级金融数据MCP服务系统 - 核心日志管理
提供统一的日志记录、性能监控和审计追踪
"""

import logging
import logging.handlers
import json
import time
import functools
from typing import Dict, Any, Optional, Callable
from datetime import datetime
from pathlib import Path
import threading
from contextlib import contextmanager

from .config import config


class StructuredFormatter(logging.Formatter):
    """结构化日志格式化器"""
    
    def format(self, record: logging.LogRecord) -> str:
        """格式化日志记录为JSON结构"""
        log_data = {
            "timestamp": datetime.fromtimestamp(record.created).isoformat(),
            "level": record.levelname,
            "logger": record.name,
            "message": record.getMessage(),
            "module": record.module,
            "function": record.funcName,
            "line": record.lineno,
            "thread": record.thread,
            "thread_name": record.threadName,
        }
        
        # 添加异常信息
        if record.exc_info:
            log_data["exception"] = self.formatException(record.exc_info)
        
        # 添加自定义字段
        if hasattr(record, 'extra_data'):
            extra_data = getattr(record, 'extra_data', None)
            if extra_data:
                log_data.update(extra_data)
        
        return json.dumps(log_data, ensure_ascii=False, separators=(',', ':'))


class PerformanceLogger:
    """性能日志记录器"""
    
    def __init__(self, logger_name: str = "performance"):
        self.logger = logging.getLogger(logger_name)
        self._local = threading.local()
    
    def start_timer(self, operation: str) -> str:
        """开始计时"""
        timer_id = f"{operation}_{int(time.time() * 1000000)}"
        if not hasattr(self._local, 'timers'):
            self._local.timers = {}
        self._local.timers[timer_id] = {
            'operation': operation,
            'start_time': time.perf_counter(),
            'start_timestamp': datetime.now().isoformat()
        }
        return timer_id
    
    def end_timer(self, timer_id: str, extra_data: Optional[Dict[str, Any]] = None):
        """结束计时并记录"""
        if not hasattr(self._local, 'timers') or timer_id not in self._local.timers:
            self.logger.warning(f"计时器 {timer_id} 不存在")
            return
        
        timer_data = self._local.timers.pop(timer_id)
        duration = time.perf_counter() - timer_data['start_time']
        
        log_data = {
            'operation': timer_data['operation'],
            'duration_seconds': duration,
            'duration_ms': duration * 1000,
            'start_timestamp': timer_data['start_timestamp'],
            'end_timestamp': datetime.now().isoformat()
        }
        
        if extra_data:
            log_data.update(extra_data)
        
        # 根据性能阈值选择日志级别
        if duration > config.monitoring.slow_query_threshold:
            self.logger.warning(f"慢操作检测", extra={'extra_data': log_data})
        else:
            self.logger.info(f"操作完成", extra={'extra_data': log_data})
    
    @contextmanager
    def timer(self, operation: str, extra_data: Optional[Dict[str, Any]] = None):
        """计时上下文管理器"""
        timer_id = self.start_timer(operation)
        try:
            yield timer_id
        finally:
            self.end_timer(timer_id, extra_data)


class AuditLogger:
    """审计日志记录器"""
    
    def __init__(self, logger_name: str = "audit"):
        self.logger = logging.getLogger(logger_name)
    
    def log_api_access(self, 
                      endpoint: str, 
                      method: str, 
                      user_id: Optional[str] = None,
                      ip_address: Optional[str] = None,
                      user_agent: Optional[str] = None,
                      status_code: Optional[int] = None,
                      response_time: Optional[float] = None,
                      extra_data: Optional[Dict[str, Any]] = None):
        """记录API访问日志"""
        log_data = {
            'event_type': 'api_access',
            'endpoint': endpoint,
            'method': method,
            'user_id': user_id,
            'ip_address': ip_address,
            'user_agent': user_agent,
            'status_code': status_code,
            'response_time_ms': response_time * 1000 if response_time else None,
            'timestamp': datetime.now().isoformat()
        }
        
        if extra_data:
            log_data.update(extra_data)
        
        self.logger.info("API访问", extra={'extra_data': log_data})
    
    def log_data_access(self,
                       data_type: str,
                       operation: str,
                       user_id: Optional[str] = None,
                       record_count: Optional[int] = None,
                       extra_data: Optional[Dict[str, Any]] = None):
        """记录数据访问日志"""
        log_data = {
            'event_type': 'data_access',
            'data_type': data_type,
            'operation': operation,
            'user_id': user_id,
            'record_count': record_count,
            'timestamp': datetime.now().isoformat()
        }
        
        if extra_data:
            log_data.update(extra_data)
        
        self.logger.info("数据访问", extra={'extra_data': log_data})
    
    def log_system_event(self,
                        event_type: str,
                        description: str,
                        severity: str = "info",
                        extra_data: Optional[Dict[str, Any]] = None):
        """记录系统事件日志"""
        log_data = {
            'event_type': 'system_event',
            'event_category': event_type,
            'description': description,
            'severity': severity,
            'timestamp': datetime.now().isoformat()
        }
        
        if extra_data:
            log_data.update(extra_data)
        
        log_level = getattr(logging, severity.upper(), logging.INFO)
        self.logger.log(log_level, description, extra={'extra_data': log_data})


class BusinessLogger:
    """业务日志记录器"""
    
    def __init__(self, logger_name: str = "business"):
        self.logger = logging.getLogger(logger_name)
    
    def log_data_sync(self,
                     data_source: str,
                     sync_type: str,
                     status: str,
                     record_count: Optional[int] = None,
                     error_message: Optional[str] = None,
                     duration: Optional[float] = None,
                     extra_data: Optional[Dict[str, Any]] = None):
        """记录数据同步日志"""
        log_data = {
            'event_type': 'data_sync',
            'data_source': data_source,
            'sync_type': sync_type,
            'status': status,
            'record_count': record_count,
            'error_message': error_message,
            'duration_seconds': duration,
            'timestamp': datetime.now().isoformat()
        }
        
        if extra_data:
            log_data.update(extra_data)
        
        if status == 'success':
            self.logger.info(f"数据同步成功: {data_source}", extra={'extra_data': log_data})
        else:
            self.logger.error(f"数据同步失败: {data_source}", extra={'extra_data': log_data})
    
    def log_cache_operation(self,
                           operation: str,
                           cache_key: str,
                           cache_level: str,
                           hit: Optional[bool] = None,
                           ttl: Optional[int] = None,
                           extra_data: Optional[Dict[str, Any]] = None):
        """记录缓存操作日志"""
        log_data = {
            'event_type': 'cache_operation',
            'operation': operation,
            'cache_key': cache_key,
            'cache_level': cache_level,
            'cache_hit': hit,
            'ttl': ttl,
            'timestamp': datetime.now().isoformat()
        }
        
        if extra_data:
            log_data.update(extra_data)
        
        self.logger.debug(f"缓存操作: {operation}", extra={'extra_data': log_data})
    
    def log_mcp_tool_execution(self,
                              tool_name: str,
                              status: str,
                              execution_time: Optional[float] = None,
                              input_params: Optional[Dict[str, Any]] = None,
                              output_size: Optional[int] = None,
                              error_message: Optional[str] = None,
                              extra_data: Optional[Dict[str, Any]] = None):
        """记录MCP工具执行日志"""
        log_data = {
            'event_type': 'mcp_tool_execution',
            'tool_name': tool_name,
            'status': status,
            'execution_time_seconds': execution_time,
            'input_params': input_params,
            'output_size_bytes': output_size,
            'error_message': error_message,
            'timestamp': datetime.now().isoformat()
        }
        
        if extra_data:
            log_data.update(extra_data)
        
        if status == 'success':
            self.logger.info(f"MCP工具执行成功: {tool_name}", extra={'extra_data': log_data})
        else:
            self.logger.error(f"MCP工具执行失败: {tool_name}", extra={'extra_data': log_data})


class LogManager:
    """统一日志管理器"""
    
    def __init__(self):
        self.performance_logger = PerformanceLogger()
        self.audit_logger = AuditLogger()
        self.business_logger = BusinessLogger()
        self.system_logger = logging.getLogger("system")
    
    def log_performance(self, operation: str, duration: float, extra_data: Optional[Dict[str, Any]] = None):
        """记录性能日志"""
        timer_id = self.performance_logger.start_timer(operation)
        self.performance_logger.end_timer(timer_id, extra_data)
    
    def log_api_access(self, endpoint: str, method: str, **kwargs):
        """记录API访问日志"""
        self.audit_logger.log_api_access(endpoint, method, **kwargs)
    
    def log_data_access(self, data_type: str, operation: str, **kwargs):
        """记录数据访问日志"""
        self.audit_logger.log_data_access(data_type, operation, **kwargs)
    
    def log_system_event(self, event_type: str, description: str, severity: str = "info", **kwargs):
        """记录系统事件日志"""
        self.audit_logger.log_system_event(event_type, description, severity, **kwargs)
    
    def log_data_sync(self, data_source: str, sync_type: str, status: str, **kwargs):
        """记录数据同步日志"""
        self.business_logger.log_data_sync(data_source, sync_type, status, **kwargs)
    
    def log_cache_operation(self, operation: str, cache_key: str, cache_level: str, **kwargs):
        """记录缓存操作日志"""
        self.business_logger.log_cache_operation(operation, cache_key, cache_level, **kwargs)
    
    def log_mcp_tool_execution(self, tool_name: str, status: str, **kwargs):
        """记录MCP工具执行日志"""
        self.business_logger.log_mcp_tool_execution(tool_name, status, **kwargs)
    
    def log_info(self, message: str, extra_data: Optional[Dict[str, Any]] = None):
        """记录信息日志"""
        if extra_data:
            self.system_logger.info(message, extra={'extra_data': extra_data})
        else:
            self.system_logger.info(message)
    
    def log_warning(self, message: str, extra_data: Optional[Dict[str, Any]] = None):
        """记录警告日志"""
        if extra_data:
            self.system_logger.warning(message, extra={'extra_data': extra_data})
        else:
            self.system_logger.warning(message)
    
    def log_error(self, message: str, extra_data: Optional[Dict[str, Any]] = None):
        """记录错误日志"""
        if extra_data:
            self.system_logger.error(message, extra={'extra_data': extra_data})
        else:
            self.system_logger.error(message)
    
    def log_debug(self, message: str, extra_data: Optional[Dict[str, Any]] = None):
        """记录调试日志"""
        if extra_data:
            self.system_logger.debug(message, extra={'extra_data': extra_data})
        else:
            self.system_logger.debug(message)


def setup_logging():
    """设置日志系统"""
    # 创建日志目录
    log_dir = Path(config.monitoring.log_file).parent
    log_dir.mkdir(parents=True, exist_ok=True)
    
    # 根日志器配置
    root_logger = logging.getLogger()
    root_logger.setLevel(getattr(logging, config.monitoring.log_level))
    
    # 清除现有处理器
    for handler in root_logger.handlers[:]:
        root_logger.removeHandler(handler)
    
    # 控制台处理器
    console_handler = logging.StreamHandler()
    console_handler.setLevel(logging.INFO)
    console_formatter = logging.Formatter(config.monitoring.log_format)
    console_handler.setFormatter(console_formatter)
    root_logger.addHandler(console_handler)
    
    # 文件处理器（结构化日志）
    file_handler = logging.handlers.RotatingFileHandler(
        config.monitoring.log_file,
        maxBytes=config.monitoring.log_max_size,
        backupCount=config.monitoring.log_backup_count,
        encoding='utf-8'
    )
    file_handler.setLevel(getattr(logging, config.monitoring.log_level))
    file_handler.setFormatter(StructuredFormatter())
    root_logger.addHandler(file_handler)
    
    # 性能日志处理器
    perf_log_file = log_dir / "performance.log"
    perf_handler = logging.handlers.RotatingFileHandler(
        perf_log_file,
        maxBytes=config.monitoring.log_max_size,
        backupCount=config.monitoring.log_backup_count,
        encoding='utf-8'
    )
    perf_handler.setFormatter(StructuredFormatter())
    perf_logger = logging.getLogger("performance")
    perf_logger.addHandler(perf_handler)
    perf_logger.setLevel(logging.DEBUG)
    
    # 审计日志处理器
    audit_log_file = log_dir / "audit.log"
    audit_handler = logging.handlers.RotatingFileHandler(
        audit_log_file,
        maxBytes=config.monitoring.log_max_size,
        backupCount=config.monitoring.log_backup_count,
        encoding='utf-8'
    )
    audit_handler.setFormatter(StructuredFormatter())
    audit_logger = logging.getLogger("audit")
    audit_logger.addHandler(audit_handler)
    audit_logger.setLevel(logging.INFO)
    
    # 业务日志处理器
    business_log_file = log_dir / "business.log"
    business_handler = logging.handlers.RotatingFileHandler(
        business_log_file,
        maxBytes=config.monitoring.log_max_size,
        backupCount=config.monitoring.log_backup_count,
        encoding='utf-8'
    )
    business_handler.setFormatter(StructuredFormatter())
    business_logger = logging.getLogger("business")
    business_logger.addHandler(business_handler)
    business_logger.setLevel(logging.INFO)


def log_performance(operation_name: str):
    """性能日志装饰器"""
    def decorator(func: Callable) -> Callable:
        @functools.wraps(func)
        async def async_wrapper(*args, **kwargs):
            perf_logger = PerformanceLogger()
            with perf_logger.timer(operation_name):
                return await func(*args, **kwargs)
        
        @functools.wraps(func)
        def sync_wrapper(*args, **kwargs):
            perf_logger = PerformanceLogger()
            with perf_logger.timer(operation_name):
                return func(*args, **kwargs)
        
        # 检查是否为协程函数
        if hasattr(func, '__code__') and func.__code__.co_flags & 0x80:
            return async_wrapper
        else:
            return sync_wrapper
    
    return decorator


# 全局日志器实例
performance_logger = PerformanceLogger()
audit_logger = AuditLogger()
business_logger = BusinessLogger()

# 初始化日志系统
setup_logging()